package com.epam.iunna.bookshop.controller.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.epam.iunna.bookshop.controller.application.App;
import com.epam.iunna.bookshop.controller.utils.RequestUtils;
import com.epam.iunna.bookshop.controller.utils.UserSessionHelper;
import com.epam.iunna.bookshop.controller.utils.StringUtils;
import com.epam.iunna.bookshop.controller.utils.dispatch.ActionFactory;
import com.epam.iunna.bookshop.controller.utils.dispatch.ActionInt;


/**
 * Класс обрабатывает запрос клиента и используя переданные параметры создает
 * класс указанного действия , выполняет его.
 */

public class CommandDispatcherFilter implements Filter {
    /**
     * Метод получает из параметра request "действие",по sid получает сессию.
     * Создает объект действия и выполняет его. Посылает запрос далее по
     * цепочке, или при успешном выполнении действия при необходимости на
     * указанный сервлет.
     * 
     * @param request
     *            запрос в которм храниться sid и действие.
     * @param response
     *            ответ на запрос.
     * @param chain
     *            обьект для передачи запроса дальше по цепочке.
     * @throws IOException
     *             должно обрабатываться при вызове chain.doFilter.
     * @throws ServletException
     *             должно обрабатываться при вызове chain.doFilter.
     */

    public void doFilter(final ServletRequest request,
            final ServletResponse response, final FilterChain chain)
            throws IOException, ServletException {
        //final String forbiden = "2";

        HttpServletRequest httpRequest = (HttpServletRequest)request; // преобразовываем
        // переменные
        HttpServletResponse httpResponse = (HttpServletResponse)response; // запроса
        // и ответа

        String userRole = new UserSessionHelper().getUserRole( httpRequest.getSession() );

        String q = getQuery(httpRequest); // представляем строку запроса в
        // виде шаблона ключ=значение&ключ2=значение2...
        
        System.out.println("Dispatch "+q);
        ActionInt action = ActionFactory.getInstance().createAction(q, userRole); // создаем
        // обьект действия название которого было указано в запросе
        // для пользователя чей идентификатор нам прислали

        if (action != null) { // если действие было создано то выполняем его
            String url = action.perform(httpRequest, httpResponse);
            if (url != null) { // если действие возвратило адрес то переходим
                // по нему
                App.initServlet.getServletContext().getRequestDispatcher(url).forward(request, response);
            } else {
                // chain.doFilter(request, response);
            }
        } else {
            // возвращаем что нет прав
           // Writer out = response.getWriter(); 
           // out.write(forbiden);
           // out.close();
            
            chain.doFilter(request, response); // переходим по цепочке на
            // сервлет или след фильтр
        }
    }

    /**
     * Получает все параметры из request как объект Properties. Преобразов. его
     * в строку вырезая фигурн. скобки, удаляя пробелы, и заменяя "," на "&"
     * (разделитель пар ключ =значение)
     * 
     * @param request
     *            данные запроса
     * @return строка отформатированная для использования в
     *         ActionFactory.createAction
     */

    private String getQuery(final HttpServletRequest request) {
        String prop = RequestUtils.getProperties(request).toString(); // получаем строку из
        // запроса
        if (prop.equals("{}")) { // если она пуста
            return "";
        }
        String[] parts = prop.substring(1, prop.length() - 1).split(","); // записываем
        // в масив без {} нашу строку где каждый элемент это одно ключ=значение
        for (int i = 0; i < parts.length; i++) { // убираем пробелы
            parts[i] = parts[i].trim();
        }
        return StringUtils.join(parts, 0, parts.length - 1, "&"); // сливаем элементы ставя
        // между ними "&"
    }

    /**
     * инициализация фильтра.
     * 
     * @param arg0
     *            конфигурация фильтра.
     * @throws ServletException .
     */
    public void init(final FilterConfig arg0) throws ServletException {
        System.out.println("start " + this.getClass().getName()); // выводим на консоль
        // имя этого класса
    }

    /**
     * Деструктор фильтра.
     */
    public void destroy() {
    }
}
